home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / grn / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-12  |  22.3 KB  |  748 lines

  1. /*    main.c    1.24    (Berkeley)    86/04/14
  2.  *
  3.  *    This file contains the main and file system dependent routines
  4.  * for processing gremlin files into troff input.  The program watches
  5.  * input go by to standard output, only interpretting things between .GS
  6.  * and .GE lines.  Default values (font, size, scale, thickness) may be
  7.  * overridden with a "default" command and are further overridden by
  8.  * commands in the input.  A description of the command-line options are
  9.  * listed below.  A space is NOT required for the operand of an option.
  10.  *
  11.  *    command options are:
  12.  *
  13.  *    -L dir    set the library directory to dir.  If a file is not found
  14.  *        in the current directory, it is looked for in dir (default
  15.  *        is /usr/lib/gremlib).
  16.  *
  17.  *    -T dev    Prepare output for "dev" printer.  Default is for the varian
  18.  *    -P dev    and versatec printers.  Devices acceptable are:  ver, var, ip.
  19.  *
  20.  *        Inside the GS and GE, commands are accepted to reconfigure
  21.  *        the picture.  At most one command may reside on each line, and
  22.  *        each command is followed by a parameter separated by white space.
  23.  *        The commands are as follows, and may be abbreviated down to one
  24.  *        character (with exception of "scale" and "stipple" down to "sc"
  25.  *        and "st") and may be upper or lower case.
  26.  *
  27.  *                  default  -  make all settings in the current
  28.  *                      .GS/.GE the global defaults.
  29.  *                      Height, width and file are NOT saved.
  30.  *               1, 2, 3, 4  -  set size 1, 2, 3, or 4 (followed
  31.  *                      by an integer point size).
  32.  *    roman, italics, bold, special  -  set gremlin's fonts to any other
  33.  *                      troff font (one or two characters)
  34.  *               stipple, l  -  use a stipple font for polygons.  Arg
  35.  *                      is troff font name.  No Default.  Can
  36.  *                      use only one stipple font per picture.
  37.  *                      (see below for stipple font index)
  38.  *                 scale, x  -  scale is IN ADDITION to the global
  39.  *                      scale factor from the default.
  40.  *               pointscale  -  turn on scaling point sizes to
  41.  *                      match "scale" commands.  (optional
  42.  *                      operand "off" to turn it off)
  43.  *        narrow, medium, thick  -  set pixel widths of lines.
  44.  *                 file  -  set the file name to read the
  45.  *                      gremlin picture from.  If the file
  46.  *                      isn't in the current directory, the
  47.  *                      gremlin library is tried.
  48.  *            width, height  -  these two commands override any
  49.  *                      scaling factor that is in effect,
  50.  *                      and forces the picture to fit into
  51.  *                      either the height or width specified,
  52.  *                      whichever makes the picture smaller.
  53.  *                      The operand for these two commands is
  54.  *                      a floating-point number in units of
  55.  *                      inches
  56.  *                oldstipplemap  -  use the old-style stipple mapping.
  57.  *                      THE FOLLOWING COMMANDS ARE IGNORED
  58.  *                      UNLESS OLDSTIPPLEMAP IS SPECIFIED.
  59.  *     l1, l2, l3, l4, l5, l6, l7, l8  -  set association between stipples
  60.  *                      (1 - 8) and the stipple font file
  61.  *                      index.  Valid cifplot indices are
  62.  *                      1 - 32 (although 24 is not defined)
  63.  *                      and valid unigrafix indices are
  64.  *                      1 - 64.  Nonetheless, any number
  65.  *                      between 0 and 255 is accepted since
  66.  *                      new stipple fonts may be added.
  67.  *                      An integer operand is required.
  68.  *
  69.  *    Troff number registers used:  g1 through g9.  g1 is the width of the
  70.  *    picture, and g2 is the height.  g3, and g4, save information, g8
  71.  *    and g9 are used for text processing and g5-g7 are reserved.
  72.  */
  73.  
  74.  
  75. #include <stdlib.h>
  76. #include <ctype.h>
  77. #include "gprint.h"
  78. #include "dev.h"
  79.  
  80. extern char *malloc();
  81. extern char *rindex();
  82.  
  83. /* database imports */
  84.  
  85. extern HGPrintElt();
  86. extern ELT *DBInit(), *DBRead();
  87. extern POINT *PTInit(), *PTMakePoint();
  88.  
  89.  
  90. #ifndef GREMLIB
  91. #define GREMLIB        "/usr/local/gremlib/"
  92. #endif
  93.  
  94. #define SUN_SCALEFACTOR 0.70
  95.  
  96. #ifndef DEVDIR
  97. #define DEVDIR        "/usr/lib/font"
  98. #endif
  99. #define DEFAULTDEV    "va"
  100. #define DEFSTIPPLE    "cf"
  101.  
  102. #define MAXINLINE    100        /* input line length */
  103. #define DEFTHICK    3        /* default thicknes */
  104. #define DEFSTYLE    SOLID        /* default line style */
  105.  
  106. #ifdef oldversion
  107. #define SCREENtoINCH    0.02        /* scaling factor, screen to inches */
  108. #endif
  109.  
  110. double SCREENtoINCH;            /* scaling factor, screen to inches */
  111.  
  112. #define BIG    999999999999.0        /* unweildly large floating number */
  113.  
  114.  
  115. static char sccsid[] = "@(#) (Berkeley) 4/14/86";
  116.  
  117. char    *printer = DEFAULTDEV;    /* device to look up resolution of */
  118. char    *gremlib = GREMLIB;    /* place to find files after current dir. */
  119. double    res;            /* that printer's resolution goes here */
  120.  
  121. int    linethickness;        /* brush styles */
  122. int    linmod;
  123. int    brushinvalid = 1;    /* non-zero means ditroff doesn't know about
  124.                  * our linethickness and linmod. */
  125. int    lastx;            /* point registers for printing elements */
  126. int    lasty;
  127. int    lastyline;        /* a line's vertical position is NOT the same */
  128.                 /* after that line is over, so for a line of */
  129.                 /* drawing commands, vertical spacing is kept */
  130.                 /* in lastyline */
  131.  
  132.             /* these are the default fonts, sizes, line styles, */
  133.             /*   and thicknesses.  These can be modified from a */
  134.             /*   "default" command and are reset each time the  */
  135.             /*   start of a picture (.GS) is found.            */
  136.  
  137. char *    deffont[] = {  "R", "I", "B", "S"  };
  138. int    defsize[] = {  10, 16, 24, 36  };
  139. int    defthick[STYLES] = {  1, 1, 5, 1, 1, 3  };
  140. int    defstipple_index[NSTIPPLES] = { 1, 3, 12, 14, 16, 19, 21, 23 };
  141. int    style[STYLES] = {  DOTTED, DOTDASHED, SOLID, DASHED, SOLID, SOLID  };
  142. double    scale = 1.0;        /* no scaling, default */
  143. int    defpoint = 0;        /* flag for pointsize scaling */
  144. char *  defstipple = (char *) 0;
  145.  
  146. int    thick[STYLES];    /* thicknesses set by defaults, then by commands */
  147. char    *tfont[FONTS];    /* fonts originally set to deffont values, then */
  148. int     tsize[SIZES];    /*    optionally changed by commands inside grn */
  149. int    stipple_index[NSTIPPLES];    /* stipple font file indices */
  150. char *  stipple;
  151.  
  152. double    xscale;        /* scaling factor from individual pictures */
  153. double    troffscale;    /* scaling factor at output time */ 
  154. double    width;        /* user-request maximum width for picture (in inches) */
  155. double    height;        /* user-request height */
  156. int    pointscale;    /* flag for pointsize scaling */
  157. int    setdefault;    /* flag for a .GS/.GE to remember all settings */
  158.  
  159. double    toppoint;        /* remember the picture */
  160. double    bottompoint;        /* bounds in these variables */
  161. double    leftpoint;
  162. double    rightpoint;
  163.  
  164. int    ytop;            /* these are integer versions of the above */
  165. int    ybottom;        /* so not to convert each time they're used */
  166. int    xleft;
  167. int    xright;
  168.  
  169. char    *filename = NULL;            /* name of input file */
  170. int    linenum = 0;            /* line number of input file */
  171. char    inputline[MAXINLINE];        /* spot to filter through the file */
  172. char    *c1 = inputline;        /* c1, c2, and c3 will be used to */
  173. char    *c2 = inputline + 1;        /* hunt for lines that begin with */
  174. char    *c3 = inputline + 2;        /* ".GS" by looking individually */
  175. char    GScommand[MAXINLINE];        /* put user's ".GS" command line here */
  176. char    gremlinfile[MAXINLINE];        /* filename to use for a picture */
  177. int    SUNFILE = FALSE;        /* TRUE if SUN gremlin file */
  178. int    oldstipmap = FALSE;        /* TRUE if old-style stipple mapping */
  179.  
  180. char *doinput();
  181.  
  182.  
  183. /*----------------------------------------------------------------------------*
  184.  | Routine:    main (argument_count, argument_pointer)
  185.  |
  186.  | Results:    parses the command line, accumulating input file names, then
  187.  |        reads the inputs, passing it directly to output until a ".GS"
  188.  |        line is read.  Main then passes control to "conv" to do the
  189.  |        gremlin file conversions.
  190.  *----------------------------------------------------------------------------*/
  191.  
  192. main(argc, argv)
  193. int argc;
  194. char **argv;
  195. {
  196.     register FILE *fp;
  197.     register int k;
  198.     register char c;
  199.     register gfil = 0;
  200.     char *file[50];
  201.  
  202.     char *operand();
  203.     char *getenv();
  204.  
  205.  
  206.     if (fp = (FILE *) getenv("PRINTER")) printer = (char *) fp;
  207.     if (fp = (FILE *) getenv("TYPESETTER")) printer = (char *) fp;
  208.     while (--argc) {
  209.         if (**++argv != '-')
  210.         file[gfil++] = *argv;
  211.         else
  212.           switch (c = (*argv)[1]) {
  213.  
  214.         case 0:
  215.             file[gfil++] = NULL;
  216.             break;
  217.  
  218.         case 'P':
  219.         case 'T':    /* final output typesetter name */
  220.             printer = operand(&argc, &argv);
  221.             break;
  222.  
  223.         case 'L':    /* set library directory */
  224.             gremlib = operand(&argc, &argv);
  225.             break;
  226.  
  227.         default:
  228.             error("unknown switch: %c", c);
  229.         }
  230.     }
  231.                 /* set the resolution for an output device */
  232.     getres(printer);    /* named in "printer" */
  233.  
  234.     if (gfil == 0) {    /* no filename, use standard input */
  235.         file[0] = NULL;
  236.         gfil++;
  237.     }
  238.  
  239.     for (k=0; k<gfil; k++) {
  240.         filename = file[k];
  241.         linenum = 0;
  242.         if (filename != NULL) {
  243.             if ((fp = fopen(filename, "r")) == NULL) {
  244.                 error("can't open file");
  245.                 exit(1);
  246.             }
  247.         } else
  248.             fp = stdin;
  249.         while (doinput(fp) != NULL) {
  250.             if (*c1 == '.' && *c2 == 'G' && *c3 == 'S') {
  251.                 conv(fp);
  252.             } else {
  253.                 fputs(inputline, stdout);
  254.             }
  255.         }
  256.     }
  257.     exit(0);
  258. }
  259.  
  260.  
  261. /*----------------------------------------------------------------------------*
  262.  | Routine:    error (control_string, args, . . . )
  263.  |
  264.  | Results:    prints ("grn: ", the control_string + args, "\n") to stderr
  265.  *----------------------------------------------------------------------------*/
  266.  
  267. /* VARARGS1 */
  268. error(s, a1, a2, a3, a4)
  269. char *    s;
  270. {
  271.     fprintf(stderr, "grn: ");
  272.     if (filename) fprintf(stderr, "\"%s\": ",filename);
  273.     if (linenum) fprintf(stderr, "line %d: ",linenum);
  274.     fprintf(stderr, s, a1, a2, a3, a4);
  275.     fprintf(stderr, "\n");
  276. }
  277.  
  278.  
  279. /*----------------------------------------------------------------------------*
  280.  | Routine:    char  * operand (& argc,  & argv)
  281.  |
  282.  | Results:    returns address of the operand given with a command-line
  283.  |        option.  It uses either "-Xoperand" or "-X operand", whichever
  284.  |        is present.  The program is terminated if no option is present.
  285.  |
  286.  | Side Efct:    argc and argv are updated as necessary.
  287.  *----------------------------------------------------------------------------*/
  288.  
  289. char *operand(argcp, argvp)
  290. int * argcp;
  291. char ***argvp;
  292. {
  293.     if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
  294.     if ((--*argcp) <= 0) {            /* no operand */
  295.         error("command-line option operand missing.");
  296.         exit(8);
  297.     }
  298.     return(*(++(*argvp)));            /* operand is next word */
  299. }
  300.  
  301.  
  302. /*----------------------------------------------------------------------------*
  303.  | Routine:    getres (device_name)
  304.  |
  305.  | Results:    sets "res" to the resolution of the output device specified
  306.  |        by the string dev.
  307.  *----------------------------------------------------------------------------*/
  308.  
  309. getres(name)
  310. char *name;
  311. {
  312.     int fin;
  313.     struct dev device;
  314.     char temp[60];
  315.  
  316.     sprintf(temp, "%s/dev%s/DESC.out", DEVDIR, name);
  317.     if ((fin = open(temp, 0)) < 0) {
  318.         error("can't open tables for %s", temp);
  319.         exit(1);
  320.     }
  321.     read(fin, &device, sizeof(struct dev));
  322.     res = (double) device.res;
  323.     close(fin);
  324. }
  325.  
  326.  
  327. /*----------------------------------------------------------------------------*
  328.  | Routine:    char  * doinput (file_pointer)
  329.  |
  330.  | Results:    a line of input is read into "inputline".
  331.  |
  332.  | Side Efct:    "linenum" is incremented.
  333.  |
  334.  | Bugs:    lines longer than MAXINLINE are NOT checked, except for 
  335.  |        updating "linenum"
  336.  *----------------------------------------------------------------------------*/
  337.  
  338. char *doinput(fp)
  339. FILE *fp;
  340. {
  341.     char *k;
  342.  
  343.  
  344.     if ((k = fgets(inputline, MAXINLINE, fp)) == NULL)
  345.     return k;
  346.     if (index (inputline, '\n'))    /* ++ only if it's a complete line */
  347.         linenum++;
  348.     return (char*) !NULL;
  349. }
  350.  
  351.  
  352. /*----------------------------------------------------------------------------*
  353.  | Routine:    initpic ( )
  354.  |
  355.  | Results:    sets all parameters to the normal defaults, possibly overridden
  356.  |        by a setdefault command.  Initilaize the picture variables,
  357.  |        and output the startup commands to troff to begin the picture.
  358.  *----------------------------------------------------------------------------*/
  359.  
  360. initpic()
  361. {
  362.     register int i;
  363.  
  364.     for (i = 0; i < STYLES; i++) {    /* line thickness defaults */
  365.     thick[i] = defthick[i];
  366.     }
  367.     for (i = 0; i < FONTS; i++) {    /* font name defaults */
  368.     tfont[i] = deffont[i];
  369.     }
  370.     for (i = 0; i < SIZES; i++) {    /* font size defaults */
  371.     tsize[i] = defsize[i];
  372.     }
  373.     for (i = 0; i < NSTIPPLES; i++) {    /* stipple font file default indices */
  374.     stipple_index[i] = defstipple_index[i];
  375.     }
  376.     stipple = defstipple;
  377.  
  378.     gremlinfile[0] = 0;        /* filename is "null" */
  379.     setdefault = 0;        /* this is not the default settings (yet) */
  380.  
  381.     toppoint = BIG;        /* set the picture bounds out */
  382.     bottompoint = -BIG;        /* of range so they'll be set */
  383.     leftpoint = BIG;        /* by "savebounds" on input */
  384.     rightpoint = -BIG;
  385.  
  386.     pointscale = defpoint;    /* Flag for scaling point sizes default. */
  387.     xscale = scale;        /* default scale of individual pictures */
  388.     width = 0.0;        /* size specifications input by user */
  389.     height = 0.0;
  390.  
  391.     linethickness = DEFTHICK;    /* brush styles */
  392.     linmod = DEFSTYLE;
  393.     brushinvalid = 1;        /* Force HGSetBrush to output brush info for
  394.                  * next element. */
  395. }
  396.  
  397.  
  398. /*----------------------------------------------------------------------------*
  399.  | Routine:    conv (file_pointer, starting_line)
  400.  |
  401.  | Results:    at this point, we just passed a ".GS" line in the input file.
  402.  |        conv reads the input and calls "interpret" to process commands,
  403.  |        gathering up information until a ".GE" line is found.  It then
  404.  |        calls "HGPrint" to do the translation of the gremlin file to
  405.  |        troff commands.
  406.  *----------------------------------------------------------------------------*/
  407.  
  408. conv(fp)
  409. register FILE *fp;
  410. {
  411.     register FILE *gfp = NULL;    /* input file pointer */
  412.     register int done = 0;        /* flag to remember if finished */
  413.     register ELT *e;    /* current element pointer */
  414.     ELT *PICTURE;        /* whole picture data base pointer */
  415.     double temp;        /* temporary calculating area */
  416.     POINT ptr;    /* coordinates of a point to pass to "mov" routine */
  417.     int flyback;    /* flag "want to end up at the top of the picture?" */
  418.  
  419.  
  420.     initpic();            /* set defaults, ranges, etc. */
  421.     strcpy (GScommand, inputline);    /* save ".GS" line for later */
  422.     do {
  423.         done = (doinput(fp) == NULL);             /* test for EOF */
  424.         flyback = *c3 == 'F';               /* and .GE or .GF */
  425.         done |= (*c1 == '.' && *c2 == 'G' && (*c3 == 'E' || flyback));
  426.  
  427.         if (done) {
  428.         if (setdefault) savestate();
  429.  
  430.         if (!gremlinfile[0]) {
  431.             if(!setdefault)
  432.             error("no picture filename");
  433.             return;
  434.         }
  435.         if ((gfp = fopen(gremlinfile, "r")) == NULL) {
  436.             char name[MAXINLINE]; /* if the file isn't in the current */
  437.                     /* directory, try the gremlin library */
  438.             sprintf(name, "%s%s", gremlib, gremlinfile);
  439.             if ((gfp = fopen(name, "r")) == NULL) {
  440.             error("can't open %s", gremlinfile);
  441.             return;
  442.             }
  443.         }
  444.         PICTURE = DBRead(gfp);            /* read picture file */
  445.         fclose(gfp);
  446.         if (DBNullelt(PICTURE))
  447.             return;        /* if a request is made to make the */
  448.                     /* picture fit into a specific area, */
  449.                     /* set the scale to do that. */
  450.  
  451.         SCREENtoINCH = (SUNFILE) ? 0.014 : 0.02;
  452.  
  453.         if (stipple == (char *) NULL)    /* if user forgot stipple */
  454.             if (has_polygon(PICTURE))    /* and picture has a polygon */
  455.             stipple = DEFSTIPPLE;    /* then set the default */
  456.  
  457.         if ((temp = bottompoint - toppoint) < 0.1) temp = 0.1;
  458.         temp = (height != 0.0) ? height / (temp * SCREENtoINCH)  : BIG;
  459.         if ((troffscale = rightpoint - leftpoint) < 0.1) troffscale=0.1;
  460.         troffscale = (width != 0.0) ?
  461.                 width / (troffscale * SCREENtoINCH)  : BIG;
  462.         if (temp == BIG && troffscale == BIG) {
  463.             troffscale = xscale;
  464.         } else {
  465.             if (temp < troffscale) troffscale = temp;
  466.         }                /* here, troffscale is the */
  467.                         /* picture's scaling factor */
  468.         if (pointscale) {
  469.             register int i;        /* do pointscaling here, when */
  470.                          /* scale is known, before output */
  471.  
  472.             for (i = 0; i < SIZES; i++)
  473.             tsize[i] = (int) (troffscale * (double) tsize[i] + 0.5);
  474.  
  475.         }
  476.                            /* change to device units */
  477.         troffscale *= SCREENtoINCH * res;    /* from screen units */
  478.  
  479.         ytop = toppoint * troffscale;        /* calculate integer */
  480.         ybottom = bottompoint * troffscale;    /* versions of the */
  481.         xleft = leftpoint * troffscale;        /* picture limits */
  482.         xright = rightpoint * troffscale;
  483.                     /* save stuff in number registers, */
  484.                     /*   register g1 = picture width and */
  485.                     /*   register g2 = picture height, */
  486.                     /*   set vertical spacing, no fill, */
  487.                     /*   and break (to make sure picture */
  488.                     /*   starts on left), and put out the */
  489.                     /*   user's ".GS" line. */
  490.         printf(
  491. ".br\n.nr g1 %du\n.nr g2 %du\n%s.nr g3 \\n(.f\n.nr g4 \\n(.s\n\\0\n.sp -1\n",
  492.             xright-xleft, ybottom-ytop, GScommand);
  493.  
  494.         if (stipple) {        /* stipple requested for this picture */
  495.             printf(".st %s\n", stipple);
  496.         }
  497.  
  498.         lastx = xleft;        /* note where we are, (upper left */
  499.         lastyline = lasty = ytop;    /* corner of the picture) */
  500.  
  501.         e = PICTURE;
  502.         while (!DBNullelt(e)) {    /* traverse picture;  print elements */
  503.             HGPrintElt(e);
  504.             e = DBNextElt(e);
  505.         }
  506.                 /* decide where to end picture */
  507.         if (flyback) {        /* end piture at upper left */
  508.             ptr.x = leftpoint;
  509.             ptr.y = toppoint;
  510.         } else {        /* end picture at lower left */
  511.             ptr.x = leftpoint;
  512.             ptr.y = bottompoint;
  513.         }
  514.         tmove(&ptr);        /* restore default line parameters, */
  515.                     /* restore everything to the way */
  516.                     /* it was before the .GS, then put */
  517.                     /* out the ".GE" line from user */
  518.         printf("\\D't %du'\\D's %du'\n", DEFTHICK, DEFSTYLE);
  519.         if (flyback) {        /* make sure we end up at top of */
  520.             printf(".sp -1\n");        /* picture if "flying back" */
  521.         }
  522.         if (stipple) {        /* restore stipple to previous */
  523.             printf(".st\n");
  524.         }
  525.         printf(".br\n.ft \\n(g3\n.ps \\n(g4\n%s", inputline);
  526.         } else {
  527.         interpret(inputline);    /* take commands from the input file */
  528.         }
  529.     } while (!done);
  530. }
  531.  
  532.  
  533. /*----------------------------------------------------------------------------*
  534.  | Routine:    savestate  ( )
  535.  |
  536.  | Results:    all the current  scaling / font size / font name / thickness /
  537.  |        pointscale  settings are saved to be the defaults.  Scaled
  538.  |        point sizes are NOT saved.  The scaling is done each time a
  539.  |        new picture is started.
  540.  |
  541.  | Side Efct:    scale, and def* are modified.
  542.  *----------------------------------------------------------------------------*/
  543.  
  544. savestate()
  545. {
  546.     register int i;
  547.  
  548.     for (i = 0; i < STYLES; i++) {    /* line thickness defaults */
  549.     defthick[i] = thick[i];
  550.     }
  551.     for (i = 0; i < FONTS; i++) {    /* font name defaults */
  552.     deffont[i] = tfont[i];
  553.     }
  554.     for (i = 0; i < SIZES; i++) {    /* font size defaults */
  555.     defsize[i] = tsize[i];
  556.     }
  557.     for (i = 0; i < NSTIPPLES; i++) {    /* stipple font file default indices */
  558.     defstipple_index[i] = stipple_index[i];
  559.     }
  560.     defstipple = stipple;    /* if stipple has been set, it's remembered */
  561.  
  562.     scale *= xscale;        /* default scale of individual pictures */
  563.     defpoint = pointscale;    /* flag for scaling pointsizes from x factors */
  564. }
  565.  
  566.  
  567. /*----------------------------------------------------------------------------*
  568.  | Routine:    savebounds (x_coordinate, y_coordinate)
  569.  |
  570.  | Results:    keeps track of the maximum and minimum extent of a picture
  571.  |        in the global variables:  left-, right-, top- and bottompoint.
  572.  |        "savebounds" assumes that the points have been oriented to
  573.  |        the correct direction.  No scaling has taken place, though.
  574.  *----------------------------------------------------------------------------*/
  575.  
  576. savebounds(x, y)
  577. float x;
  578. float y;
  579. {
  580.     if (x < leftpoint) leftpoint = x;
  581.     if (x > rightpoint) rightpoint = x;
  582.     if (y < toppoint) toppoint = y;
  583.     if (y > bottompoint) bottompoint = y;
  584. }
  585.  
  586.  
  587. /*----------------------------------------------------------------------------*
  588.  | Routine:    interpret (character_string)
  589.  |
  590.  | Results:    commands are taken from the input string and performed.
  591.  |        Commands are separated by the endofline, and are of the
  592.  |        format:
  593.  |            string1 string2
  594.  |
  595.  |        where string1 is the command and string2 is the argument.
  596.  |
  597.  | Side Efct:    font and size strings, plus the gremlin file name and the
  598.  |        width and height variables are set by this routine.
  599.  *----------------------------------------------------------------------------*/
  600.  
  601. interpret (line)
  602. char *line;
  603. {
  604.     char str1[MAXINLINE];
  605.     char str2[MAXINLINE];
  606.     register char *chr;
  607.     register int i;
  608.     double par;
  609.  
  610.     str2[0] = '\0';
  611.     sscanf(line, "%80s%80s", &str1[0], &str2[0]);
  612.     for (chr = &str1[0]; *chr; chr++)        /* convert command to */
  613.     if(isupper(*chr)) *chr = tolower(*chr);        /* lower case */
  614.     switch (str1[0]) {
  615.  
  616.     case '1':
  617.     case '2':    /* font sizes */
  618.     case '3':
  619.     case '4':
  620.         i = atoi(str2);
  621.         if (i > 0 && i < 1000)
  622.         tsize[str1[0] - '1'] = i;
  623.         else
  624.         error("bad font size value");
  625.         break;
  626.  
  627.     case 'r':    /* roman */
  628.         if(str2[0] < '0') goto nofont;
  629.         tfont[0] = malloc(strlen(str2) + 1);
  630.         strcpy(tfont[0], str2);
  631.         break;
  632.  
  633.     case 'i':    /* italics */
  634.         if(str2[0] < '0') goto nofont;
  635.         tfont[1] = malloc(strlen(str2) + 1);
  636.         strcpy(tfont[1], str2);
  637.         break;
  638.  
  639.     case 'b':    /* bold */
  640.         if(str2[0] < '0') goto nofont;
  641.         tfont[2] = malloc(strlen(str2) + 1);
  642.         strcpy(tfont[2], str2);
  643.         break;
  644.  
  645.     case 's':    /* special */
  646.         if (str1[1] == 'c') goto scalecommand;    /* or scale */
  647.  
  648.         if(str2[0] < '0') {
  649.     nofont:    error("no fontname specified");
  650.         break;
  651.         }
  652.         if (str1[1] == 't') goto stipplecommand;    /* or stipple */
  653.  
  654.         tfont[3] = malloc(strlen(str2) + 1);
  655.         strcpy(tfont[3], str2);
  656.         break;
  657.  
  658.     case 'l':    /* l */
  659.         if ((str1[1] < '1') || (str1[1] > '8'))
  660.         goto stipplecommand;
  661.  
  662.         /* else set stipple index */
  663.         i = atoi(str2);
  664.         if (i >= 0 && i < 256)
  665.         stipple_index[str1[1] - '1'] = i;
  666.         else
  667.         error("bad stipple index value");
  668.         break;
  669.  
  670.     stipplecommand:    /* stipple */
  671.         stipple = malloc(strlen(str2) + 1);
  672.         strcpy(stipple, str2);
  673.         break;
  674.  
  675.     case 'o':    /* oldstipplemap */
  676.         oldstipmap = TRUE;
  677.         break;
  678.  
  679.     case 't':    /* thick */
  680.         thick[2] = atoi(str2);
  681.         break;
  682.  
  683.     case 'm':    /* medium */
  684.         thick[5] = atoi(str2);
  685.         break;
  686.  
  687.     case 'n':    /* narrow */
  688.         thick[0] = thick[1] = thick[3] = thick[4] = atoi(str2);
  689.         break;
  690.  
  691.     case 'x':    /* x */
  692.     scalecommand:    /* scale */
  693.         par = atof(str2);
  694.         if (par > 0.0)
  695.         xscale *= par;
  696.         else
  697.         error("illegal scale value");
  698.         break;
  699.  
  700.     case 'f':    /* file */
  701.         strcpy(gremlinfile, str2);
  702.         break;
  703.  
  704.     case 'w':    /* width */
  705.         width = atof(str2);
  706.         if (width < 0.0) width = -width;
  707.         break;
  708.  
  709.     case 'h':    /* height */
  710.         height = atof(str2);
  711.         if (height < 0.0) height = -height;
  712.         break;
  713.  
  714.     case 'd':    /* defaults */
  715.         setdefault = 1;
  716.         break;
  717.  
  718.     case 'p':    /* pointscale */
  719.         if (strcmp("off", str2))
  720.         pointscale = 1;
  721.         else
  722.         pointscale = 0;
  723.         break;
  724.  
  725.     default: 
  726.         error("unknown command, %s",str1);
  727.         exit(8);
  728.         break;
  729.     };
  730. }
  731.  
  732.  
  733. /*
  734.  * return TRUE if picture contains a polygon
  735.  * otherwise FALSE
  736.  */
  737. has_polygon(elist)
  738. register ELT *elist;
  739. {
  740.     while (!DBNullelt(elist)) {
  741.     if (elist->type == POLYGON)
  742.         return(1);
  743.     elist = DBNextElt(elist);
  744.     }
  745.  
  746.     return(0);
  747. }
  748.